package com.dsg.service.bank.impl;

import com.alibaba.excel.EasyExcel;
import com.alibaba.excel.ExcelWriter;
import com.alibaba.excel.write.metadata.WriteSheet;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.metadata.OrderItem;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.dsg.common.security.SystemAuthorizingUser;
import com.dsg.common.util.DateUtils;
import com.dsg.common.util.FileUtils;
import com.dsg.common.util.SingletonLoginUtils;
import com.dsg.common.util.UUIDGenerator;
import com.dsg.common.util.toolbox.CollectionUtil;
import com.dsg.dao.account.DsgAccountCardMapper;
import com.dsg.dao.bank.DsgBankRecordMapper;
import com.dsg.entity.account.DsgAccountCard;
import com.dsg.entity.account.DsgAccountTrade;
import com.dsg.entity.bank.DsgBankDetail;
import com.dsg.entity.bank.DsgBankRecord;
import com.dsg.service.DsgServiceImpl;
import com.dsg.service.account.IDsgAccountTradeService;
import com.dsg.service.bank.IDsgBankDetailService;
import com.dsg.service.bank.IDsgBankRecordService;
import com.dsg.support.LeveldbAccess;
import com.dsg.util.EasyExcelUtils;
import com.dsg.util.RRException;
import com.dsg.util.VersionException;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.compress.archivers.ArchiveEntry;
import org.apache.commons.compress.archivers.zip.Zip64Mode;
import org.apache.commons.compress.archivers.zip.ZipArchiveEntry;
import org.apache.commons.compress.archivers.zip.ZipArchiveOutputStream;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.servlet.http.HttpServletResponse;
import java.io.ByteArrayOutputStream;
import java.io.OutputStream;
import java.math.BigDecimal;
import java.net.URLEncoder;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;

/**
 * <p>
 * 銀行往來過數檔案 服务实现类
 * </p>
 *
 * @author system
 * @since 2020-07-12
 */
@Service
@Slf4j
public class DsgBankRecordServiceImpl extends DsgServiceImpl<DsgBankRecordMapper, DsgBankRecord> implements IDsgBankRecordService {

    @Autowired
    private IDsgBankDetailService dsgBankDetailService;
    @Autowired
    private DsgBankRecordMapper dsgBankRecordMapper;
    @Autowired
    private DsgAccountCardMapper dsgAccountCardMapper;
    @Autowired
    private IDsgAccountTradeService dsgAccountTradeService;
    @Autowired
    private LeveldbAccess leveldbAccess;


    @Override
    @Transactional(rollbackFor = Exception.class)
    public void batchDelete(String idList) {
        QueryWrapper queryWrapper = new QueryWrapper();
        queryWrapper.in("OID", Arrays.asList(idList.split(",")));
        List<DsgBankRecord> dsgBankRecordList = list(queryWrapper);
        if (CollectionUtil.isNotEmpty(dsgBankRecordList)) {
            List<String> keyList = new ArrayList<>();
            try {
                String oid = UUIDGenerator.getUUID();
                SystemAuthorizingUser user = SingletonLoginUtils.getSystemUser();
                //取油咭總賬并缓存
                QueryWrapper<DsgAccountCard> cardQueryWrapper = new QueryWrapper<>();
                cardQueryWrapper.eq("ENT_CODE", user.getOrgCode());
                List<DsgAccountCard> dsgAccountCardList = dsgAccountCardMapper.selectList(cardQueryWrapper);
                dsgAccountCardList.forEach(I -> {
                    String key = leveldbAccess.genCacheKey(oid, DsgAccountCard.class.getSimpleName(), I.getCardNo());
                    leveldbAccess.put(key, I);
                    keyList.add(key);
                });
                dsgAccountCardList.clear();
                List<DsgAccountCard> upDsgAccountCard = new ArrayList<>();
                List<DsgAccountTrade> addDatList = new ArrayList<>();
                for (DsgBankRecord dsgBankRecord : dsgBankRecordList) {
                    if (DsgBankRecord.AppStatus.newGeneration.getCode().intValue() != dsgBankRecord.getStatus().intValue()) {
                        throw new RRException(String.format("狀態為非新生成，不能刪除操作！"));
                    }
                    List<DsgAccountTrade> dsgAccountTradeList = dsgBankDetailService.selectDsgAccountTradeList(dsgBankRecord.getOid());
                    dsgAccountTradeList.forEach(I -> {
                        BigDecimal traAmount = I.getTraAmount();
                        DsgAccountTrade dsgAccountTrade = new DsgAccountTrade();
                        BeanUtils.copyProperties(I, dsgAccountTrade);
                        dsgAccountTrade.setOid(UUIDGenerator.getUUID());
                        if (I.getInOut().equals("IN")) {
                            dsgAccountTrade.setInOut("OUT");
                            traAmount = BigDecimal.ZERO.subtract(traAmount);
                        } else {
                            dsgAccountTrade.setInOut("IN");
                        }
                        String key = leveldbAccess.genCacheKey(oid, DsgAccountCard.class.getSimpleName(), I.getCardNo());
                        DsgAccountCard dsgAccountCard = leveldbAccess.get(key);
                        if (dsgAccountCard != null) {
                            //承前結欠
                            dsgAccountTrade.setPreDept(dsgAccountCard.getArrearsValue());
                            //结欠金額
                            dsgAccountCard.setArrearsValue(dsgAccountCard.getArrearsValue().add(I.getTraAmount()));
                            //總結欠
                            dsgAccountTrade.setAftDept(dsgAccountCard.getArrearsValue());
                            //待過數金額
                            dsgAccountCard.setWaitPostValue(dsgAccountCard.getWaitPostValue().add(traAmount));
                            dsgAccountCard.setTradeId(dsgAccountTrade.getOid());
                            upDsgAccountCard.add(dsgAccountCard);
                        }
                        dsgAccountTrade.setTranItem(DsgAccountTrade.AppStatus.deleteList.getCode());
                        dsgAccountTrade.setCreateTime(null);
                        dsgAccountTrade.setCreater(null);
                        dsgAccountTrade.setUpdateTime(null);
                        dsgAccountTrade.setUpdater(null);
                        dsgAccountTrade.setBankDetailId(null);
                        addDatList.add(dsgAccountTrade);
                    });
                    QueryWrapper delQueryWrapper = new QueryWrapper();
                    delQueryWrapper.eq("RECORD_ID", dsgBankRecord.getOid());
                    dsgBankDetailService.remove(delQueryWrapper);
                }
                remove(queryWrapper);
                //保存交易賬目
                if (CollectionUtil.isNotEmpty(addDatList)) {
                    dsgAccountTradeService.saveBatch(addDatList);
                } else {
                    throw new RRException("交易賬目數為空！");
                }
                //更新咭總賬
                upDsgAccountCard.forEach(I -> {
                    if (dsgAccountCardMapper.updateById(I) <= 0) {
                        throw new VersionException();
                    }
                });
            } finally {
                if (CollectionUtil.isNotEmpty(keyList)) {
                    keyList.forEach(I -> leveldbAccess.delete(I));
                }
            }
        }
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void downloadBea(HttpServletResponse response, DsgBankRecord dsgBankRecord) throws Exception {
        // 分頁
        Page page = new Page();
        List<OrderItem> orderItemList = new ArrayList<>();
        orderItemList.add(new OrderItem().setColumn("CREATE_TIME").setAsc(false));
        page.setOrders(orderItemList);
        page.setSize(EasyExcelUtils.PER_WRITE_ROW_COUNT);
        SystemAuthorizingUser systemUser = SingletonLoginUtils.getSystemUser();
        response.setContentType("application/zip");
        response.setCharacterEncoding("utf-8");
        String fileName = "過數銀行_" + systemUser.getInputCopName() + "_" + DateUtils.getStringDate() + ".zip";
        response.setHeader("Content-disposition", "attachment; filename=" + URLEncoder.encode(fileName, "utf-8"));
        OutputStream out = response.getOutputStream();
        //壓縮
        ZipArchiveOutputStream zous = new ZipArchiveOutputStream(out);
        zous.setUseZip64(Zip64Mode.AsNeeded);
        DsgBankDetail dsgBankDetail = new DsgBankDetail();
        dsgBankDetail.setRecordId(dsgBankRecord.getOid());
//        dsgBankDetail.setStatus(DsgBankDetail.AppStatus.generated.getCode()); //可重復下載
        dsgBankDetail.setFlag("1");
        String templateFileName = FileUtils.getExcelTemplatePath("bankABea.xlsx");
        fileName = systemUser.getInputCopName() + "_" + DateUtils.getStringDate() + "_Bea.xlsx";
        this.writerFill(zous, page, dsgBankDetail, templateFileName, fileName);
        dsgBankDetail.setFlag("0");
        templateFileName = FileUtils.getExcelTemplatePath("bankANonbea.xlsx");
        fileName = systemUser.getInputCopName() + "_" + DateUtils.getStringDate() + "_Nonbea.xlsx";
        this.writerFill(zous, page, dsgBankDetail, templateFileName, fileName);
        //回填狀態
        dsgBankRecord.setStatus(DsgBankRecord.AppStatus.settledBank.getCode());
        dsgBankRecordMapper.updateById(dsgBankRecord);
        zous.close();
    }

    /**
     * 生成Excel文件添加到壓縮文件
     *
     * @param zous
     * @param page
     * @param dsgBankDetail
     * @param templateFileName 模板文件
     * @param fileName         生成文件
     * @throws Exception
     */
    private void writerFill(ZipArchiveOutputStream zous, Page page, DsgBankDetail dsgBankDetail,
                            String templateFileName, String fileName) throws Exception {
        int currentPage = 0;
        List<DsgBankDetail> dsgBankDetailList;
        BigDecimal tranValue = BigDecimal.ZERO;
        ByteArrayOutputStream bos = new ByteArrayOutputStream();
        ExcelWriter excelWriter = EasyExcel.write(bos).withTemplate(templateFileName).build();
        WriteSheet writeSheet = EasyExcel.writerSheet(0).build();
        do {
            page.setCurrent(++currentPage);
            dsgBankDetailList = dsgBankDetailService.selectByList(page, dsgBankDetail).getRecords();
            if (CollectionUtil.isNotEmpty(dsgBankDetailList)) {
                for (DsgBankDetail detail : dsgBankDetailList) {
                    tranValue = tranValue.add(detail.getTranValue());
                    detail.setCusNo(detail.getFlowNo());
                    detail.setStatus(DsgBankDetail.AppStatus.remitted.getCode());
                }
                excelWriter.fill(dsgBankDetailList, writeSheet);
                log.info("寫銀行過數據數據{}条", dsgBankDetailList.size());
                //回填狀態
                dsgBankDetailService.updateBatchById(dsgBankDetailList);
            }
        } while (CollectionUtil.isNotEmpty(dsgBankDetailList) && dsgBankDetailList.size() == EasyExcelUtils.PER_WRITE_ROW_COUNT);
        if (CollectionUtil.isNotEmpty(dsgBankDetailList)) {
            dsgBankDetailList.clear();
            dsgBankDetailList.add(new DsgBankDetail());
            DsgBankDetail detail = new DsgBankDetail();
            detail.setBankCode("Total:");
            detail.setTranValue(tranValue);
            dsgBankDetailList.add(detail);
            excelWriter.fill(dsgBankDetailList, writeSheet);
            excelWriter.finish();
            //设置文件名
            ArchiveEntry entry = new ZipArchiveEntry(fileName);
            zous.putArchiveEntry(entry);
            zous.write(bos.toByteArray());
            zous.closeArchiveEntry();
            bos.close();
        }
    }

    @Override
    public Page<DsgBankRecord> selectByGroupList(Page<DsgBankRecord> page, DsgBankRecord dsgBankRecord) {
        return page.setRecords(dsgBankRecordMapper.selectByGroupList(page, dsgBankRecord));
    }
}
